﻿using Actors.ActorComponents;
using Actors.Actions;
using GameStates;
using UnityEngine;

namespace Actors
{
    public class LocalPlayer : Player
    {
        private readonly StateMachine m_MovementStateMachine = new StateMachine();

        private CharacterController m_CharacterController;
        public LocalPlayer()
        {
            RegistryActionExecutors();
        }

        #region Initialization

        public override void Initialize(ActorInitParams initParams)
        {
            base.Initialize(initParams);

            var actionIdle = Action.GetAction<Act_Idle>();
            ExecuteAction(actionIdle);
            Action.ReturnAction(actionIdle);
            
            m_CharacterController = gameObject.AddComponent<CharacterController>();
            m_CharacterController.center = BodyInfo.center;
            m_CharacterController.height = BodyInfo.height;
            m_CharacterController.radius = BodyInfo.radius;
            
        }

        protected override void InitComponents()
        {
            AddActorComponent(new InputComponent());
            
            foreach (var component in Components)
            {
                component.Initialize(this);
            }
        }

        private void RegistryActionExecutors()
        {
            BindActionExecutor<Act_Idle>(ExecuteAction);
            BindActionExecutor<Act_Move>(ExecuteAction);
            BindActionExecutor<Act_Jump>(ExecuteAction);
            BindActionExecutor<Act_Fall>(ExecuteAction);
            BindActionExecutor<Act_Land>(ExecuteAction);
        }
        #endregion

        public override void Update()
        {
            base.Update();
            m_MovementStateMachine.Update();
        }

        public override void FixedUpdate()
        {
            m_MovementStateMachine.FixedUpdate();
        }

        #region Movement

        public override void Move(Vector2 movementInput)
        {
            m_CharacterController.Move(new Vector3(movementInput.x, 0, movementInput.y));
        }

        public override void Move(Vector3 movementInput)
        {
            m_CharacterController.Move(movementInput);
        }

        #endregion

        #region Execute Action
        
        /*
        private bool ExecuteMovementAction<Ta, Ts>(Ta action) where Ta : Action where Ts : CharacterState, new()
        {
            if (m_MovementStateMachine.CurrentState is Ts)
            {
                return false;
            }
            var idle = State.Get<Ts>();
            idle.Initialize(this);
            m_MovementStateMachine.ChangeState(idle);
            return true;
        }
        */
        private bool ExecuteAction(Act_Idle action)
        {
            if (m_MovementStateMachine.CurrentState is Idle)
            {
                return false;
            }
            var idle = StatePool.Get<Idle>();
            idle.Initialize(this);
            m_MovementStateMachine.ChangeState(idle);

            m_CharacterVisual.OnActionIdle();
            return true;
        }

        private bool ExecuteAction(Act_Move action)
        {
            // 这里执行命令只负责进行状态转换，具体的逻辑在状态类中处理
            if (m_MovementStateMachine.CurrentState is Move)
            {
                return false;
            }
            var move = StatePool.Get<Move>();
            move.Initialize(this);
            move.movementInput = action.MovementInput;
            m_MovementStateMachine.ChangeState(move);
            
           m_CharacterVisual.OnActionMove();
            return true;
        }
        
        private bool ExecuteAction(Act_Jump action)
        {
            if (m_MovementStateMachine.CurrentState is Jump)
            {
                return false;
            }
            var jump = StatePool.Get<Jump>();
            jump.Initialize(this);
            m_MovementStateMachine.ChangeState(jump);
            
            m_CharacterVisual.OnActionJump();
            return true;
        }
        
        private bool ExecuteAction(Act_Fall action)
        {
            if (m_MovementStateMachine.CurrentState is Fall)
            {
                return false;
            }
            var fall = StatePool.Get<Fall>();
            fall.Initialize(this);
            m_MovementStateMachine.ChangeState(fall);
            
            m_CharacterVisual.OnActionFall();
            return true;
        }

        private bool ExecuteAction(Act_Land action)
        {
            if (m_MovementStateMachine.CurrentState is Land)
            {
                return false;
            }
            var land = StatePool.Get<Land>();
            land.Initialize(this);
            m_MovementStateMachine.ChangeState(land);
            
            m_CharacterVisual.OnActionLand();
            return true;
        }

        #endregion
        
    }
}